﻿using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using Modelica.CoreLite;
using Modelica.ModelicaTypes;
using OmcSocketClient;
using System.Windows.Controls.Primitives;
using DrawToolsLib;


namespace DrawTools {
    
    // TODO: prejmenovat namespaces a Page1 pro nasi aplikaci
    // TODO: pridat do kazdeho souboru informaci o projektu, copyrightu, verzi !
    // TODO: v kazdem souboru by se na teto pozici mely zobrazovat informace pro ostatni...
    //  o tom, co jeste nefunguje, co je treba dodelat, na co si dat bacha a na co nesahat
    // TODO: pridat do projektu zminku o pouziti knihovny DrawToolsWPF + autora

    public partial class Page1 : Page {

        #region Class Members

        private GridLength lastLeftExpanderWidth;
        private GridLength lastRightExpanderWidth;
        private bool hiddenPanels = false;
        private List<string> omcCommandHistory = new List<string>();
        private int omcCommandHistoryIdx = -1;
        private ModelicaClass[] mclass;        
        private bool openedFile = false;
        private TabItem lastSelectedTabItem = null;

        #endregion Class Members

        #region Constructor

        public Page1()
        {
            InitializeComponent();

            //testing icons
            LoadPreviewIcons();
        }

        /// <summary>
        /// internal function for testing IconEditor panels. 
        /// </summary>
        private void LoadPreviewIcons() {

            mclass = new ModelicaClass[3];
            Annotations.InitializeIcons(mclass);

        }

        #endregion Constructor

        #region Application Commands
        
        private void NewCommand( object sender , ExecutedRoutedEventArgs e ) {            
            
        }        

        private void OpenCommand( object sender , ExecutedRoutedEventArgs e ) {


            FilesForOpenListBox.Items.Clear();
            OpenFileOkBtn.IsEnabled = false;

            List<ServerModelList> models = omc.GetListOfModelsOnServer();
            foreach( ServerModelList tmp in models ) {
                ListBoxItem item = new ListBoxItem();
                item.Tag = tmp;
                if( tmp.RelativeDirectory == "\\" ) {
                    item.Content = tmp.RelativeDirectory + tmp.FileName;
                } else {
                    item.Content = tmp.RelativeDirectory + "\\" + tmp.FileName;
                }
                item.Selected +=new RoutedEventHandler( OpenFileListBoxItem_Selected );
                item.MouseDoubleClick += new MouseButtonEventHandler( OpenFileListBoxItem_MouseDoubleClick );
                FilesForOpenListBox.Items.Add( item );
            }

            MainPage.IsEnabled = false;
            OpenFileDialog.IsOpen = true;                        

        }

        private void hideOpenFileDialog() {
            OpenFileDialog.IsOpen = false;
            MainPage.IsEnabled = true;
        }

        void OpenFileListBoxItem_MouseDoubleClick( object sender , MouseButtonEventArgs e ) {            
            hideOpenFileDialog();
            openFile( ( (ListBoxItem)FilesForOpenListBox.SelectedItem ).Tag as ServerModelList );
        }

        void OpenFileListBoxItem_Selected( object sender , RoutedEventArgs e ) {
            OpenFileOkBtn.IsEnabled = true;
        }

        private void openFile( ServerModelList fileForOpen ) {

            bool succes = false;
            
            succes = Core.LoadModel( fileForOpen.FileName , fileForOpen.RelativeDirectory );

            if( succes ) {

                List<ModelicaClass> topClasses = Core.GetModelStructure();

                foreach( var modelicaClass in topClasses ) {
                    modelicaTreeViewItem item = new modelicaTreeViewItem( modelicaClass );
                    item.PreviewMouseDoubleClick += modelTreeViewItemClicked;
                    item.Header = modelicaClass.ToString();
                    item.Foreground = modelStructureTreeView.Foreground;
                    modelStructureTreeView.Items.Add( item );
                    fillModelTreeView( item , modelicaClass );

                }

                openedFile = true;

            } else { 
            
                //TODO: Chtelo by to udelat nejaky globalni dialog pro zobrazovani informaci

            }
            
        }

        private void fillModelTreeView( modelicaTreeViewItem item , ModelicaClass modelicaClasses ) {
            
            foreach( var modelicaClass in modelicaClasses.ContainedClasses ) {
                modelicaTreeViewItem newItem = new modelicaTreeViewItem( modelicaClass );
                newItem.PreviewMouseDoubleClick += modelTreeViewItemClicked;
                newItem.Header = modelicaClass.ToString();
                newItem.Foreground = item.Foreground;
                item.Items.Add( newItem );                
                fillModelTreeView( newItem , modelicaClass );                
            }

        }

        private void SaveCommand( object sender , ExecutedRoutedEventArgs e ) {            
            foreach( TreeViewItem item in modelStructureTreeView.Items ) {
                Core.UpdateClassIcon( ( (modelicaTreeViewItem)item ).ModelicaItem );
            }            
        }

        private void CanExecuteSaveCommand( object sender , CanExecuteRoutedEventArgs e ) {

            if( openedFile ) {
                ( (Image)saveBtn.Content ).Source = new System.Windows.Media.Imaging.BitmapImage( new Uri( "Images/save_24_hot.ico" , UriKind.Relative ) );
                e.CanExecute = true;
            } 

        }

        private void SaveAsCommand( object sender , ExecutedRoutedEventArgs e ) {

        }

        #endregion ApplicationCommands

        #region ToolBar Event Handlers

        private void Left_Expander_Collapsed( object sender , RoutedEventArgs e ) {

            lastLeftExpanderWidth = workArea.ColumnDefinitions[0].Width;
            workArea.ColumnDefinitions[0].Width = new GridLength( 23 );
        }

        private void Left_Expander_Expanded( object sender , RoutedEventArgs e ) {
            workArea.ColumnDefinitions[0].Width = lastLeftExpanderWidth;
        }

        private void Right_Expander_Collapsed( object sender , RoutedEventArgs e ) {
            lastRightExpanderWidth = workArea.ColumnDefinitions[4].Width;
            workArea.ColumnDefinitions[4].Width = new GridLength( 23 );
        }

        private void Right_Expander_Expanded( object sender , RoutedEventArgs e ) {
            workArea.ColumnDefinitions[4].Width = lastRightExpanderWidth;
        }

        private void hideAllPanels( object sender , RoutedEventArgs e ) {

            if( hiddenPanels ) {
                hideBtnTxt.Text = "Hide all panels";
            } else {
                hideBtnTxt.Text = "Show all panels";
            }

            leftExpander.IsExpanded = hiddenPanels;
            rightExpander.IsExpanded = hiddenPanels;
            downExpander.IsExpanded = hiddenPanels;
            hiddenPanels = !hiddenPanels;

        }

        #endregion ToolBar Event Handlers

        #region Editor Tools Event Handlers

        /// <summary>
        /// Handles the KeyUp event of the omcRequestTxt control. 
        /// If Enter is pressed, then commadn from omcRequestTxt control is sent to OMC server.
        /// Keys Up and Down can be used for searching in commnads history.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Input.KeyEventArgs"/> instance containing the event data.</param>
        private void omcRequestTxtKeyUp( object sender , KeyEventArgs e ) {
            
            //enter key is pressed
            if(e.Key == Key.Enter) {

                //deleting old history
                for( int i = omcCommandHistory.Count - 1 ; i > omcCommandHistoryIdx ; i-- ) {
                    omcCommandHistory.RemoveAt( i );
                }
                                
                //new command added to history
                omcCommandHistory.Add( omcRequestTxt.Text );
                omcCommandHistoryIdx = omcCommandHistory.Count;
                
                //showing results
                omcResultTxt.Text += "\n";
                omcResultTxt.Text += omcRequestTxt.Text;
                omcResultTxt.Text += "\n";
                omcResultTxt.Text += omcSocketClient.send( omcRequestTxt.Text );
                omcResultTxt.ScrollToEnd();
                
                omcRequestTxt.Text = "";
              
  
            //key up is pressed - searching in history
            } else if( e.Key == Key.Up) {

                if( omcCommandHistory.Count > 0 ) {                
                    omcCommandHistoryIdx--;

                    if ( omcCommandHistoryIdx < 0 ) {
                        omcCommandHistoryIdx = 0;
                    }

                    omcRequestTxt.Text = omcCommandHistory[omcCommandHistoryIdx];
                }

            //key down is pressed - searching in history
            } else if( e.Key == Key.Down) {

                if( omcCommandHistory.Count > 0 ) {
                    omcCommandHistoryIdx++;

                    if ( omcCommandHistoryIdx > omcCommandHistory.Count - 1 ) {
                        omcCommandHistoryIdx = omcCommandHistory.Count - 1;
                    }
                    
                    omcRequestTxt.Text = omcCommandHistory[omcCommandHistoryIdx];
                }

            }
        }

        /// <summary>
        /// Double click handler for tree view
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Windows.Input.MouseButtonEventArgs"/> instance containing the event data.</param>
        private void modelTreeViewItemClicked( object sender , MouseButtonEventArgs e ) {            
            addTabItem( ( (modelicaTreeViewItem)modelStructureTreeView.SelectedItem ).ModelicaItem );
            e.Handled = true;
        }

        //for testing...will be removed
        //private void TabControl_MouseDoubleClick( object sender , MouseButtonEventArgs e ) {
        //    helpTxt.Text += "tab control mouse double click";
        //}

        #endregion Editor Tools Event Handlers
        
        //for testing...will be deleted
        #region Button event handlers

        /// <summary>
        /// When double clicking on item representing Icon, create new IconEditor tab and add it to TabControl
        /// </summary>
        private void ListBoxItem_MouseDoubleClick(object sender, MouseButtonEventArgs e) {
            ListBoxItem li = sender as ListBoxItem;
            addTabItem( mclass[int.Parse( li.Tag.ToString() )] );
        }

        /// <summary>
        /// Create new IconEditor tab and add it to TabControl.
        /// </summary>
        /// <param name="icon">The icon which will be showed in Icon Editor</param>
        /// <param name="headerText">The header text of the TabItem</param>
        private void addTabItem( ModelicaClass mclass ) {            
            foreach( TabItem ti in TabPanel.Items ) {
                if( ti.Content is IconEditor ) {
                    if( ( ti.Content as IconEditor ).Mclass == mclass ) {
                        // if yes, just show it
                        ti.IsSelected = true;
                        return;
                    }
                }
            }
            
            TabItem t = new TabItem();
            IconEditor ie = new IconEditor( mclass );            
            t.Content = ie;
            t.Header = new TextBlock( new Run( mclass.Name ) );
            ( t.Header as TextBlock ).Text = mclass.Name;
            ( t.Header as TextBlock ).MouseDown += new MouseButtonEventHandler( RemoveTab_MouseDown );
            TabPanel.SelectionChanged += new SelectionChangedEventHandler( TabPanel_SelectionChanged );
            

            // add it to TabControl and show it
            TabPanel.Items.Add( t );
            t.IsSelected = true;
            
            //IsChecked="{Binding Path=Tool, Converter={StaticResource convToolType}, ConverterParameter=Text, ElementName=drawingCanvas, Mode=OneWay}">
            
            //Command="MediaCommands.Select" CommandParameter="{Binding ElementName=buttonToolText, Path=Tag}"
        }

        void TabPanel_SelectionChanged( object sender , SelectionChangedEventArgs e ) {

            if( lastSelectedTabItem != null && !lastSelectedTabItem.Equals( TabPanel.SelectedItem ) ) {
                Core.UpdateClassIcon( ( lastSelectedTabItem.Content as IconEditor ).Mclass );
            }

            //event is also invoked when tab is removed, for this situation is this condition
            if( TabPanel.SelectedItem == null ) {
                lastSelectedTabItem = null;
                return;
            }            


            // TODO: Smazat podminku az se v aplikaci nebudou vyskytovat testovanci ikony vpravo v list boxu
            string iconName = ( (TextBlock)( (TabItem)TabPanel.SelectedItem ).Header ).Text;            
            if( iconName != "Icon 1" && iconName != "Icon 2" && iconName != "Icon 3" ) {
                lastSelectedTabItem = (TabItem)TabPanel.SelectedItem;
            } else {
                lastSelectedTabItem = null;
            }
                                    
        }
        

        /// <summary>
        /// Removes itself from parent TabControl.
        /// </summary>
        void RemoveTab_MouseDown(object sender, MouseButtonEventArgs e) {
            // TODO: pridat kontrolu, zda mohu provest odebrani z TabControlu
            if (e.ClickCount == 2) {
            //Here might be some check like "save or not?"
                TabPanel.Items.Remove((sender as TextBlock).Parent);
            }

        }
        
        /// <summary>
        /// An Event fired, when any toolbar button is checked.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param> 
        private void Tool_Checked(object sender, RoutedEventArgs e) {
            ToggleButton tb = sender as ToggleButton;
            ToggleButton[] tblist = new ToggleButton[]{buttonToolPointer, buttonToolRectangle,
                buttonToolEllipse, buttonToolLine, buttonToolPencil, buttonToolText};
            foreach (ToggleButton t in tblist) {
                if (t != tb) {
                    t.IsChecked = false;
                }
            }
            DrawingTools.ToolType = (ToolType)Enum.Parse(typeof(ToolType), tb.Tag.ToString());
        }

        /// <summary>
        /// Handles the Click event of the Cancel Button in Open file dialog.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void OpenFileCancelBtn_Click( object sender , RoutedEventArgs e ) {
            hideOpenFileDialog();
        }

        private void OpenFileOkBtn_Click( object sender , RoutedEventArgs e ) {
            hideOpenFileDialog();
            openFile( ( (ListBoxItem)FilesForOpenListBox.SelectedItem ).Tag as ServerModelList );
        }

        #endregion Button event handlers                 
        
    }

    /// <summary>
    /// Class for model structure view
    /// </summary>
    public class modelicaTreeViewItem : TreeViewItem {

        private ModelicaClass modelicaItem;

        public modelicaTreeViewItem( ModelicaClass item ) {
            modelicaItem = item;
        }

        public ModelicaClass ModelicaItem { get { return modelicaItem; } }        

        public override string ToString() {
            return modelicaItem.ToString();
        }
    }
}
